﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Reflection;
using log4net;
using Safover.LidarCollector.Core;

namespace Om.Default
{
    public class NJOpticalMaserDevice : OpticalMaserDevice
    {
        private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

        internal const int FIXED_PACKET_LENGTH = 40;

        #region Singleton
        public static OpticalMaserDevice Instance { get; } = new NJOpticalMaserDevice();

        private NJOpticalMaserDevice()
        {
            PortName = "COM1";

            BaudRate = 19200;
        }

        #endregion

        public override string DeviceType => "NJOpticalMaserDevice";

        public override void ErrorReset()
        {
            throw new NotImplementedException();
        }

        public override bool StartLasar()
        {
            byte[] open = new byte[] { 0x55, 0xaa, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x33, 0xcc };

            bool success = Write(open);

            IsLaserOpened = true;
            InvokeReadingsUpdated(true);

            return success;
        }

        public override bool StopLasar()
        {
            byte[] close = new byte[] { 0x55, 0xaa, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x33, 0xcc };

            bool success = Write(close);

            IsLaserOpened = false;
            InvokeReadingsUpdated(true);

            return success;
        }

        protected override void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {
                var packet = ReadPacket();

                if (packet == null)
                {
                    return;
                }

                switch (packet.PacketType)
                {
                    case PacketType.MainBoard:
                        {
                            InternalTriggerFrequency = (packet as MainBoardPacket).InternalTriggerFrequency;
                        }
                        break;
                    case PacketType.DriverBoard:
                        {
                            ElectricityRealValue = (packet as DriverBoardPacket).ElectricityRealValue;

                            var e1 = BitConverter.ToUInt16(new byte[] { packet.RawBytes[6], packet.RawBytes[7] }, 0) / 100;
                            var e2 = BitConverter.ToUInt16(new byte[] { packet.RawBytes[7], packet.RawBytes[6] }, 0) / 100;
                        }
                        break;
                    case PacketType.TemperatureBoardLD:
                        {
                            LDTemperature = (packet as LDTemperatureBoardPacket).Temperature;
                        }
                        break;
                    case PacketType.TemperatureBoardLaserCrystal:
                        {
                            LaserCrystalTemperature = (packet as LaserCrystalTemperatureBoardPacket).Temperature;
                        }
                        break;
                    case PacketType.TemperatureBoardFrequencyDoublingCrystal:
                        {
                            FrequencyDoublingCrystalTemperature = (packet as FrequencyDoublingCrystalTemperatureBoardPacket).Temperature;
                        }
                        break;
                    default:
                        break;
                }


                InvokeReadingsUpdated(false);
            }
            catch (Exception ex)
            {
                Log.Error($"{DeviceType}: OnDataReceived error.", ex);
            }
            
        }

        private int count = 0;
        private void InvokeReadingsUpdated(bool forceInvoke)
        {
            if (!forceInvoke && count++ % 10 != 0) return;

            var args = new OpticalMaserReadingsUpdatedEventArgs
            {
                IsLasarOpen = IsLaserOpened,
                InternalTriggerFrequency = InternalTriggerFrequency,
                ElectricityRealValue = ElectricityRealValue,

                LDTemperature = LDTemperature,
                LaserCrystalTemperature = LaserCrystalTemperature,
                FrequencyDoublingCrystalTemperature = FrequencyDoublingCrystalTemperature,

                LaserWorkingTime = LaserWorkingTime,
            };


            DeviceReadingsUpdated?.Invoke(this, args);
        }

        
        private NJOpticalMaserPacket ReadPacket()
        {
            byte[] buffer = new byte[FIXED_PACKET_LENGTH];

            try
            {
                if (!Read(buffer, 0, FIXED_PACKET_LENGTH))
                {
                }
            }
            catch (Exception ex)
            {
                Log.Error($"{DeviceType}: ex.Message", ex);
            }

            var packet = NjOpticalMaserPacketFactory.BuildPacket(buffer);

            if (packet == null)
            {
                byte h0xAA = 0xAA;

                var temp = new List<byte>();
                byte[] errorBuffer = new byte[1];

                do
                {
                    _ = Read(errorBuffer, 0, errorBuffer.Length);

                    temp.AddRange(errorBuffer);

                } while (errorBuffer[0] != h0xAA);

                byte[] errorTail = new byte[FIXED_PACKET_LENGTH - 1];
                _ = Read(errorTail, 0, errorTail.Length);
            }

            return packet;
        }

        private string Checksum(string str)
        {
            string[] array = str.Split(new char[]
            {
                ' '
            });
            int num = 0;
            for (int i = 0; i < 8; i++)
            {
                num += Convert.ToInt32(array[i], 16);
            }
            return str + " " + (num & 255).ToString("X2") + " 33 CC";
        }
    }

}
